package com.ruoyi.web.controller.file;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.util.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringMD5Checksum;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;


/**
 * @author: pch
 * @description: 视频分段播放
 * @date: 2020/10/27
 **/
@RestController
@RequestMapping("/shareDive/file")
public class FileController extends BaseController {

    private String UPLOAD_DIR(){
        return  RuoYiConfig.getProfile() +  System.getProperty("file.separator") + "shareDive" + System.getProperty("file.separator") + SecurityUtils.getLoginUser().getUserId() + System.getProperty("file.separator") ;
    }

    private static Map<String, String> fileList = new HashMap<String,String>();

    @RequestMapping(value = "/test/{id}",method = RequestMethod.POST)
    public R<JSONObject> downFile(@PathVariable String id) throws IOException {
        JSONObject re = new JSONObject();
        re.put("hasFile",fileList.get(id) != null ? "yes" : "no");
        return R.ok(re);

    }

    @RequestMapping(value = "/list",method = RequestMethod.POST)
    public  R<List> fileList(){

        List reList = new ArrayList();
        File[] fileArr = new File(UPLOAD_DIR()).listFiles();
        for(File tempFile : fileArr){
            if(tempFile.isFile()){
                Map fileMess = new HashMap();
                String id = StringMD5Checksum.getStringMD5Checksum(tempFile.getAbsolutePath());
                fileMess.put("id", id);
                fileMess.put("name",tempFile.getName());
                fileMess.put("fileLength",(tempFile.length()/1024/1024/1024) > 1 ? (tempFile.length()/1024/1024/1024) + " GB" : ((tempFile.length()/1024/1024) > 1 ? (tempFile.length()/1024/1024) + " MB" : (tempFile.length()/1024) + " KB"));
                reList.add(fileMess);
                fileList.put(id,tempFile.getAbsolutePath());
            }
        }

        return R.ok(reList);

    }

    @Anonymous
    @RequestMapping(value = "/download",method = RequestMethod.GET)
    public void downFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String fileId = request.getParameter("id");
        String filePath = fileList.get(fileId);
        File tempFile = new File(filePath);
        if(filePath == null || !tempFile.isFile()){
            response.getWriter().print("error not findFile");
            return;
        }

        response.setContentType("application/octet-stream");
        response.setHeader("Accept-Ranges", "bytes");
        response.setHeader("Last-Modified", new Date().toString());
        response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(tempFile.getName().getBytes(), StandardCharsets.ISO_8859_1) + "\"");

        sendFile(request, response, tempFile);
    }


    private void sendFile(HttpServletRequest request, HttpServletResponse response, File file) throws FileNotFoundException, IOException {
        RandomAccessFile randomFile = new RandomAccessFile(file, "r");//只读模式
        long contentLength = randomFile.length();
        String range = request.getHeader("Range");
        Long start = 0L, end = 0L;
        if (range != null && range.startsWith("bytes=")) {
            String[] values = range.split("=")[1].split("-");
            start = Long.parseLong(values[0]);
            if (values.length > 1) {
                end = Long.parseLong(values[1]);
            }
        }
        Long requestSize = 0L;
        if (end != 0 && end > start) {
            requestSize = (end - start + 1);
        } else {
            requestSize = requestSize.MAX_VALUE;
        }

        byte[] buffer = new byte[4096];

        //第一次请求只返回content length来让客户端请求多次实际数据
        if (range == null) {
            response.setHeader("Content-length", contentLength + "");
        } else {
            //以后的多次以断点续传的方式来返回视频数据
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206
            long requestStart = 0, requestEnd = 0;
            String[] ranges = range.split("=");
            if (ranges.length > 1) {
                String[] rangeDatas = ranges[1].split("-");
                requestStart = Long.parseLong(rangeDatas[0]);
                if (rangeDatas.length > 1) {
                    requestEnd = Long.parseLong(rangeDatas[1]);
                }
            }
            long length = 0;
            if (requestEnd > 0) {
                length = requestEnd - requestStart + 1;
                response.setHeader("Content-length", "" + length);
                response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);
            } else {
                length = contentLength - requestStart;
                response.setHeader("Content-length", "" + length);
                response.setHeader("Content-Range", "bytes " + requestStart + "-" + (contentLength - 1) + "/" + contentLength);
            }
        }
        ServletOutputStream out = response.getOutputStream();
        Long needSize = requestSize;
        randomFile.seek(start);
        while (needSize > 0) {
            int len = randomFile.read(buffer);
            if (needSize < buffer.length) {
                out.write(buffer, 0, needSize.intValue());
            } else {
                out.write(buffer, 0, len);
                if (len < buffer.length) {
                    break;
                }
            }
            needSize -= buffer.length;
        }

        out.flush();
        randomFile.close();
        out.close();

    }

}
